package Interfaz;

import AnalizadorLexico.*;
import AnalizadorSintactico.AnalizadorSintactico;

import java.awt.BorderLayout;
import java.awt.Event;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;

/*
 * CompiladorVentana.java
 *
 * Created on 26 de agosto de 2008, 23:11
 */
import javax.swing.text.DefaultEditorKit;
import javax.swing.tree.DefaultTreeModel;

/**
 *
 * @author Juan Pablo
 */
public class CompiladorVentana extends javax.swing.JFrame {

    FileFilter filtro;
    JFileChooser chooser;
    AnalizadorLexico analizador;
    Modelo modeloLexico, modeloError;
    JTable tablaLexico, tablaError;

    /** Creates new form CompiladorVentana */
    public CompiladorVentana() {
        filtro = new FilterSimple("Monky Files(.monky)", ".monky");
        chooser = new JFileChooser(".");
        chooser.addChoosableFileFilter(filtro);
        initComponents();
        setLocationRelativeTo(null);
        barraDeHerramientas.setFloatable(false);
        setExtendedState(MAXIMIZED_BOTH);
        divisor.setDividerLocation(getHeight() / 100 * 50);
        ActionMap acciones = editor.getActionMap();
        Action accionCopiar = acciones.get(DefaultEditorKit.copyAction);
        Action accionPegar = acciones.get(DefaultEditorKit.pasteAction);
        Action accionCortar = acciones.get(DefaultEditorKit.cutAction);
        accionCopiar.putValue(Action.NAME, "Copy");
        accionCopiar.putValue(Action.ACCELERATOR_KEY, KeyStroke.getAWTKeyStroke('C', Event.CTRL_MASK));

        accionCortar.putValue(Action.NAME, "Cut");
        accionCortar.putValue(Action.ACCELERATOR_KEY, KeyStroke.getAWTKeyStroke('X', Event.CTRL_MASK));

        accionPegar.putValue(Action.NAME, "Paste");
        accionPegar.putValue(Action.ACCELERATOR_KEY, KeyStroke.getAWTKeyStroke(
                'V', Event.CTRL_MASK));
        editar.add(accionCortar);
        editar.add(accionCopiar);
        editar.add(accionPegar);
        salida.setEditable(false);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        barraDeHerramientas = new javax.swing.JToolBar();
        jLabel3 = new javax.swing.JLabel();
        nuevo = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        abrir = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        guardar = new javax.swing.JButton();
        separador1 = new javax.swing.JToolBar.Separator();
        analizarLexico = new javax.swing.JButton();
        jSplitPane1 = new javax.swing.JSplitPane();
        divisor = new javax.swing.JSplitPane();
        pestana = new javax.swing.JTabbedPane();
        panelSalida = new javax.swing.JPanel();
        scrollSalida = new javax.swing.JScrollPane();
        salida = new javax.swing.JTextArea();
        panelLexico = new javax.swing.JPanel();
        panelError = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        editor = new Interfaz.EditorTexto();
        jScrollPane2 = new javax.swing.JScrollPane();
        arbolSintactico = new javax.swing.JTree();
        menu = new javax.swing.JMenuBar();
        archivo = new javax.swing.JMenu();
        nuevoMenu1 = new javax.swing.JMenuItem();
        separador4 = new javax.swing.JSeparator();
        guardarMenu1 = new javax.swing.JMenuItem();
        abrirMenu1 = new javax.swing.JMenuItem();
        separador5 = new javax.swing.JSeparator();
        salir1 = new javax.swing.JMenuItem();
        editar = new javax.swing.JMenu();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Banana Compiler"); // NOI18N
        setBackground(new java.awt.Color(255, 255, 0));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
            public void windowClosed(java.awt.event.WindowEvent evt) {
                formWindowClosed(evt);
            }
        });
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });

        barraDeHerramientas.setBorder(null);
        barraDeHerramientas.setRollover(true);

        jLabel3.setText(" ");
        barraDeHerramientas.add(jLabel3);

        nuevo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Imagenes/stock_insert-fields.png"))); // NOI18N
        nuevo.setToolTipText("New File"); // NOI18N
        nuevo.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        nuevo.setFocusable(false);
        nuevo.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        nuevo.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        nuevo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nuevoActionPerformed(evt);
            }
        });
        barraDeHerramientas.add(nuevo);

        jLabel1.setText(" ");
        barraDeHerramientas.add(jLabel1);

        abrir.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Imagenes/stock_open.png"))); // NOI18N
        abrir.setToolTipText("Open File"); // NOI18N
        abrir.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        abrir.setFocusable(false);
        abrir.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        abrir.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        abrir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                abrirActionPerformed(evt);
            }
        });
        barraDeHerramientas.add(abrir);

        jLabel2.setText(" ");
        barraDeHerramientas.add(jLabel2);

        guardar.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Imagenes/stock_export.png"))); // NOI18N
        guardar.setToolTipText("Save File"); // NOI18N
        guardar.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        guardar.setFocusable(false);
        guardar.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        guardar.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        guardar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                guardarActionPerformed(evt);
            }
        });
        barraDeHerramientas.add(guardar);
        barraDeHerramientas.add(separador1);

        analizarLexico.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Imagenes/stock_compile.png"))); // NOI18N
        analizarLexico.setToolTipText("Compile"); // NOI18N
        analizarLexico.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        analizarLexico.setFocusable(false);
        analizarLexico.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        analizarLexico.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        analizarLexico.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                analizarLexicoActionPerformed(evt);
            }
        });
        barraDeHerramientas.add(analizarLexico);

        getContentPane().add(barraDeHerramientas, java.awt.BorderLayout.NORTH);

        jSplitPane1.setDividerLocation(200);

        divisor.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
        divisor.setDividerLocation(250);
        divisor.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        panelSalida.setLayout(new java.awt.BorderLayout());

        salida.setColumns(20);
        salida.setRows(5);
        scrollSalida.setViewportView(salida);

        panelSalida.add(scrollSalida, java.awt.BorderLayout.CENTER);

        pestana.addTab("Console", panelSalida);

        panelLexico.setLayout(new java.awt.BorderLayout());
        pestana.addTab("Lexic", panelLexico);

        panelError.setLayout(new java.awt.BorderLayout());
        pestana.addTab("Mistake", panelError);

        divisor.setBottomComponent(pestana);

        editor.setColumns(20);
        editor.setRows(5);
        editor.setTabSize(4);
        editor.setFont(new java.awt.Font("Courier New", 0, 12)); // NOI18N
        jScrollPane1.setViewportView(editor);

        divisor.setLeftComponent(jScrollPane1);

        jSplitPane1.setRightComponent(divisor);

        jScrollPane2.setBorder(javax.swing.BorderFactory.createTitledBorder("Arbol Sintactico"));

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        arbolSintactico.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        jScrollPane2.setViewportView(arbolSintactico);

        jSplitPane1.setLeftComponent(jScrollPane2);

        getContentPane().add(jSplitPane1, java.awt.BorderLayout.CENTER);

        archivo.setText("File"); // NOI18N
        archivo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                archivo2ActionPerformed(evt);
            }
        });

        nuevoMenu1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
        nuevoMenu1.setText("New"); // NOI18N
        nuevoMenu1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nuevoMenuActionPerformed(evt);
            }
        });
        archivo.add(nuevoMenu1);
        archivo.add(separador4);

        guardarMenu1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        guardarMenu1.setText("Save"); // NOI18N
        guardarMenu1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                guardarMenuActionPerformed(evt);
            }
        });
        archivo.add(guardarMenu1);

        abrirMenu1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        abrirMenu1.setText("Open"); // NOI18N
        abrirMenu1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                abrirMenuActionPerformed(evt);
            }
        });
        archivo.add(abrirMenu1);
        archivo.add(separador5);

        salir1.setText("Exit"); // NOI18N
        salir1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                salirActionPerformed(evt);
            }
        });
        archivo.add(salir1);

        menu.add(archivo);

        editar.setText("Edit"); // NOI18N
        menu.add(editar);

        setJMenuBar(menu);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void formComponentResized(java.awt.event.ComponentEvent evt) {// GEN-FIRST:event_formComponentResized
        divisor.setDividerLocation(getHeight() / 100 * 65);
    }// GEN-LAST:event_formComponentResized

    private void nuevoActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_nuevoActionPerformed
        int opcion = JOptionPane.showConfirmDialog(null,
                "Do you want to create a new document?", "New",
                JOptionPane.OK_CANCEL_OPTION);
        if (opcion == 0) {
            editor.setText("");
        }
    }// GEN-LAST:event_nuevoActionPerformed

    private void nuevoMenuActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_nuevoMenuActionPerformed
        int opcion = JOptionPane.showConfirmDialog(null,
                "Do you want to create a new document?", "New",
                JOptionPane.OK_CANCEL_OPTION);
        if (opcion == 0) {
            editor.setText("");
        }
    }// GEN-LAST:event_nuevoMenuActionPerformed

    private void abrirActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_abrirActionPerformed
        int aprobado = chooser.showOpenDialog(this);
        if (aprobado == JFileChooser.APPROVE_OPTION) {
            File directorio = chooser.getSelectedFile();
            try {
                ObjectInputStream entrada = new ObjectInputStream(
                        new FileInputStream(directorio));
                String str = (String) entrada.readObject();
                editor.setText(str);
                entrada.close();
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Error de Lectura",
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }// GEN-LAST:event_abrirActionPerformed

    private void guardarActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_guardarActionPerformed
        int aprobado = chooser.showSaveDialog(this);
        if (aprobado == JFileChooser.APPROVE_OPTION) {
            File directorio = chooser.getSelectedFile();
            ObjectOutputStream file;
            try {
                if (directorio.getAbsolutePath().contains(".")) {
                    file = new ObjectOutputStream(new FileOutputStream(
                            directorio));
                } else {
                    file = new ObjectOutputStream(new FileOutputStream(
                            directorio + ".monky"));
                }
                file.writeObject(editor.getText());
                file.close();
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Error de escritura",
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }// GEN-LAST:event_guardarActionPerformed

    private void salirActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_salirActionPerformed
        int opcion = JOptionPane.showConfirmDialog(null,
                "Do you want to close the application?", "Close",
                JOptionPane.OK_CANCEL_OPTION);
        if (opcion == 0) {
            System.exit(0);
        }
    }// GEN-LAST:event_salirActionPerformed

    private void abrirMenuActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_abrirMenuActionPerformed
        int aprobado = chooser.showOpenDialog(this);
        if (aprobado == JFileChooser.APPROVE_OPTION) {
            File directorio = chooser.getSelectedFile();
            try {
                ObjectInputStream entrada = new ObjectInputStream(
                        new FileInputStream(directorio));
                String str = (String) entrada.readObject();
                editor.setText(str);
                entrada.close();
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Error de Lectura",
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }// GEN-LAST:event_abrirMenuActionPerformed

    private void guardarMenuActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_guardarMenuActionPerformed
        int aprobado = chooser.showSaveDialog(this);
        if (aprobado == JFileChooser.APPROVE_OPTION) {
            File directorio = chooser.getSelectedFile();
            ObjectOutputStream file;
            try {
                if (directorio.getAbsolutePath().contains(".")) {
                    file = new ObjectOutputStream(new FileOutputStream(
                            directorio));
                } else {
                    file = new ObjectOutputStream(new FileOutputStream(
                            directorio + ".monky"));
                }
                file.writeObject(editor.getText());
                file.close();
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Error de escritura",
                        "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }// GEN-LAST:event_guardarMenuActionPerformed

    private void formWindowClosed(java.awt.event.WindowEvent evt) {// GEN-FIRST:event_formWindowClosed
    }// GEN-LAST:event_formWindowClosed

    private void archivo2ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_archivo2ActionPerformed
        // TODO add your handling code here:
    }// GEN-LAST:event_archivo2ActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt) {// GEN-FIRST:event_formWindowClosing
    }// GEN-LAST:event_formWindowClosing

    private void analizarLexicoActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_analizarLexicoActionPerformed
        salida.setText("");
        panelLexico.removeAll();
        panelError.removeAll();
        try {
            salida.setText("");
            analizador = new AnalizadorLexico();
            analizador.analizar(editor.getText());
            ArrayList<Lexema> lexico = analizador.getTablaDeSimbolos();
            AnalizadorSintactico miSintactico = new AnalizadorSintactico();
            miSintactico.analizar(lexico);
            ArrayList<String> erroresSintacticos = miSintactico.getErrores();
            DefaultTreeModel dtm = new DefaultTreeModel(miSintactico.getSubArbol());
            arbolSintactico.setModel(dtm);
            ArrayList<ErrorLexico> error = analizador.getTablaDeErrores();
            String[] nombre = new String[]{"Token", "Lexema", "Fila",
                "Columna"};
            Object[][] contenido = new Object[lexico.size()][4];
            for (int i = 0; i < lexico.size(); i++) {
                contenido[i][0] = ((Lexema) lexico.get(i)).getLexema();
                contenido[i][1] = ((Lexema) lexico.get(i)).getTipo();
                contenido[i][2] = ((Lexema) lexico.get(i)).getFila();
                contenido[i][3] = ((Lexema) lexico.get(i)).getColumna();

            }
            modeloLexico = new Modelo(contenido, nombre);
            nombre = new String[]{"Token", "Lexema", "Fila", "Columna",
                        "Sugerencia"};
            contenido = new Object[error.size()][5];
            for (int i = 0; i < error.size(); i++) {
                contenido[i][0] = ((ErrorLexico) error.get(i)).getLexema();
                contenido[i][1] = ((ErrorLexico) error.get(i)).getTipo();
                contenido[i][2] = ((ErrorLexico) error.get(i)).getFila();
                contenido[i][3] = ((ErrorLexico) error.get(i)).getColumna();
                contenido[i][4] = ((ErrorLexico) error.get(i)).getSugerencia();
            }
            modeloError = new Modelo(contenido, nombre);
            tablaLexico = new JTable(modeloLexico);
            tablaError = new JTable(modeloError);
            tablaLexico.getTableHeader().setReorderingAllowed(false);
            tablaError.getTableHeader().setReorderingAllowed(false);
            JScrollPane scrollTablaLexico = new JScrollPane(tablaLexico);
            JScrollPane scrollTablaError = new JScrollPane(tablaError);
            panelLexico.add(scrollTablaLexico, BorderLayout.CENTER);
            panelError.add(scrollTablaError, BorderLayout.CENTER);
            pestana.repaint();
            salida.append("Analisis Lexico completado\n");
            for (String i : erroresSintacticos) {
                salida.append(i);
            }
        } catch (Exception ex) {
            salida.append("Analisis Lexico Fallido\n");
        }
    }// GEN-LAST:event_analizarLexicoActionPerformed

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String args[]) {

        try {
        	UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");

        } catch (Exception e) {
        }

        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new CompiladorVentana().setVisible(true);
            }
        });

    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton abrir;
    private javax.swing.JMenuItem abrirMenu1;
    private javax.swing.JButton analizarLexico;
    private javax.swing.JTree arbolSintactico;
    private javax.swing.JMenu archivo;
    private javax.swing.JToolBar barraDeHerramientas;
    private javax.swing.JSplitPane divisor;
    private javax.swing.JMenu editar;
    private Interfaz.EditorTexto editor;
    private javax.swing.JButton guardar;
    private javax.swing.JMenuItem guardarMenu1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JMenuBar menu;
    private javax.swing.JButton nuevo;
    private javax.swing.JMenuItem nuevoMenu1;
    private javax.swing.JPanel panelError;
    private javax.swing.JPanel panelLexico;
    private javax.swing.JPanel panelSalida;
    private javax.swing.JTabbedPane pestana;
    private javax.swing.JTextArea salida;
    private javax.swing.JMenuItem salir1;
    private javax.swing.JScrollPane scrollSalida;
    private javax.swing.JToolBar.Separator separador1;
    private javax.swing.JSeparator separador4;
    private javax.swing.JSeparator separador5;
    // End of variables declaration//GEN-END:variables
}
